{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Julia\n",
    "## Install IJulia\n",
    "\n",
    "[IJulia](https://github.com/JuliaLang/IJulia.jl) is Jupyter kernel for Julia\n",
    "\n",
    "Install [Julia](https://julialang.org/) firstly, then in Julia REPL\n",
    "```julia\n",
    "julia>\n",
    "using Pkg\n",
    "Pkg.add(\"IJulia\")\n",
    "Pkg.build(\"ZMQ\")\n",
    "Pkg.build(\"IJulia\")\n",
    "```\n",
    "and finally start the notebook with ```jupyter notebook```\n",
    "\n",
    "[Learn Julia in Y minutes](https://learnxinyminutes.com/docs/julia/)\n",
    "\n",
    "Enjoy!\n",
    "\n",
    "Julia Version 1.1.0\n",
    "\n",
    "Just type `?` for help, or [Julia Docs](https://docs.julialang.org)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Contents\n",
    "- [Datatypes](#Julia-Datatypes,-Variables-and-Collections)\n",
    "- [Functions](#Julia-Functions,-Control-Flow-and-Types)\n",
    "- [Parallel Computing](#Parallel-Computing)\n",
    "- [Multi-dimensional Arrays](#Multi-dimensional-Arrays)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello Julia\n"
     ]
    }
   ],
   "source": [
    "println(\"Hello Julia\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Julia Datatypes, Variables and Collections"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Int64, Int8, Int16, Int32, Int64, Int128, UInt64, UInt8, UInt16, UInt32, UInt64, UInt128, Float16, Float32, Float64, Inf, NaN, BigInt, BigFloat)"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Int,Int8,Int16,Int32,Int64,Int128,UInt,UInt8,UInt16,UInt32,UInt64,UInt128,Float16,Float32,Float64,Inf,NaN,BigInt,BigFloat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(-9223372036854775808, 9223372036854775807)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "typemin(Int), typemax(Int)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Int64, UInt8, UInt16, UInt8, Complex{Int64}, Rational{Int64})"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "typeof(1),typeof(0x1),typeof(0x123),typeof(0b101),typeof(2 + 1im),typeof(2 // 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(true, false)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "true, false"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "57.400000000000006"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "const x = 8\n",
    "2x^2 - 6.3(x+4) + 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0, 0.0)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "zero(x), zero(Float64)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "2 < x < 9"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(8, Int32)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "let x::Int32 = 8; x,typeof(x) end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(16, 384)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gcd(128,48), lcm(128, 48)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "12.041594578792296"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "hypot(8,9)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "40 + 5im"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# complex\n",
    "5(1 + 2im)*(2 - 3im)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "11//8"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# fraction\n",
    "1 + 6//16"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"0000000000000000000000000000000000000000000000000000001101111000\""
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bitstring(888)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"0011111111010011001100110011001100110011001100110011001100110011\""
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bitstring(0.3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(String, Char)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s=\"julia\"\n",
    "typeof(s), typeof('a')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"good\" > \"bye\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('j', 'a', \"uli\")"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# based on 1\n",
    "s[1], s[end], s[2:4]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(65, 'Y')"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Int('A'), Char(89)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"Hello julia 8\""
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "h = \"Hello $s $(3+5)\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(\"**********\", 13)"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "repeat(\"*\",10), length(h)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "demo 5.30\n"
     ]
    }
   ],
   "source": [
    "using Printf\n",
    "@printf \"demo %0.2f\\n\" 5.3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[34mHello julia 8\u001b[39m"
     ]
    }
   ],
   "source": [
    "printstyled(h, color=:blue)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3-element Array{Int64,1}:\n",
       " 8\n",
       " 6\n",
       " 4"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = [8,6,4]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3-element Array{Int32,1}:\n",
       " 7\n",
       " 1\n",
       " 9"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = Int32[7;1;9]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4-element Array{Int64,1}:\n",
       " 8\n",
       " 6\n",
       " 4\n",
       " 8"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "push!(a, 8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pop!(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6-element Array{Int64,1}:\n",
       " 8\n",
       " 6\n",
       " 4\n",
       " 7\n",
       " 1\n",
       " 9"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "append!(a, b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "popfirst!(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6-element Array{Int64,1}:\n",
       " 7\n",
       " 6\n",
       " 4\n",
       " 7\n",
       " 1\n",
       " 9"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pushfirst!(a, 7)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Remove elements from an array by index with splice\n",
    "splice!(a, 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(5, false)"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "length(a), in(2, a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5-element Array{Int64,1}:\n",
       " 1\n",
       " 4\n",
       " 7\n",
       " 7\n",
       " 9"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sort(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5-element Array{Int64,1}:\n",
       " 1\n",
       " 4\n",
       " 7\n",
       " 7\n",
       " 9"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sort!(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2×3 Array{Int64,2}:\n",
       " 3  6  1\n",
       " 4  2  5"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "matrix = [3 6 1; 4 2 5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2×3 Array{Int64,2}:\n",
       " 3  2  1\n",
       " 4  6  5"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sort(matrix, dims=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2×3 Array{Int64,2}:\n",
       " 1  3  6\n",
       " 2  4  5"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sort(matrix, dims=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(UnitRange{Int64}[1:5], [1, 2, 3, 4, 5])"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[1:5],[1:5;]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tuples like arrays, but are immutable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(5, 4)"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# swap values\n",
    "m, n = (4 ,5)\n",
    "m, n = n, m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Dictionaries store unordered mappings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Dict{String,Int64} with 3 entries:\n",
       "  \"two\"   => 2\n",
       "  \"one\"   => 1\n",
       "  \"three\" => 3"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dict = Dict(\"one\" => 1, \"two\" => 2, \"three\" => 3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, [\"two\", \"one\", \"three\"], [2, 1, 3])"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dict[\"two\"], keys(dict), values(dict)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "get(dict, \"three\", 4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "get(dict, \"four\", 4)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Sets store unordered, unique values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Set([4, 2, 3, 1])"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "seta = Set([1, 2, 2, 3, 4])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Set([4, 3, 5, 6])"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "setb = Set([3, 4, 5, 6])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Set([4, 3]), Set([4, 2, 3, 5, 6, 1]), Set([2, 1]))"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "intersect(seta, setb), union(seta, setb), setdiff(seta, setb)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Julia Functions, Control Flow and Types\n",
    "Julia functions are first class\n",
    "\n",
    "Functions support varargs, positional arguments, keyword arguments and multiple dispatch(overload)\n",
    "\n",
    "Names of functions and macros are in lower case, without underscores.\n",
    "\n",
    "Functions that modify their inputs have names that end in !"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "bar (generic function with 1 method)"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "function bar(x,y)\n",
    "  x + y\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "67"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "foo(x,y) = 3x^2 + 8y\n",
    "foo(3,5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3-element Array{Float64,1}:\n",
       " 79.0 \n",
       " 28.25\n",
       " 16.49"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "map(x -> x^2 + 2x - 1, [8, 4.5, 3.3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4-element Array{Int64,1}:\n",
       "  0\n",
       "  4\n",
       " -3\n",
       "  1"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# mulit line\n",
    "map([-8, 4, -3, 0]) do x\n",
    "    if x < 0 && iseven(x)\n",
    "        return 0\n",
    "    elseif x == 0\n",
    "        return 1\n",
    "    else\n",
    "        return x\n",
    "    end\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: redefining constant x\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z = (x = 1; y = 2; x + y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "begin\n",
    "    x = 1; \n",
    "    y = 2;\n",
    "    if x < y\n",
    "        x + y\n",
    "    else\n",
    "        x * y\n",
    "    end\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "min(x, y) = x < y ? x : y; min(3,4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "40320"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# error() throw ErrorException\n",
    "# warn() info()\n",
    "function factorial(n::Int)\n",
    "    n == 0 && return 1\n",
    "    n >= 0 || error(\"n must be non-negative\")\n",
    "    n * factorial(n-1)\n",
    "end\n",
    "factorial(8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "occur error ErrorException(\"n must be non-negative\")\n"
     ]
    }
   ],
   "source": [
    "try factorial(-4)\n",
    "catch e\n",
    "    println(\"occur error \", e)\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Functions Multiple dispatch"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((9.100000000000001, \"float version\"), (15, \"int version\"))"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "foo(x::Float64, y::Float64) = 2x + y, \"float version\"\n",
    "foo(x::Int, y::Int) = 2x + y, \"int version\"\n",
    "foo(3.2, 2.7), foo(4, 7)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "3 methods for generic function <b>foo</b>:<ul><li> foo(x::<b>Int64</b>, y::<b>Int64</b>) in Main at In[56]:2</li> <li> foo(x::<b>Float64</b>, y::<b>Float64</b>) in Main at In[56]:1</li> <li> foo(x, y) in Main at In[48]:1</li> </ul>"
      ],
      "text/plain": [
       "# 3 methods for generic function \"foo\":\n",
       "[1] foo(x::Int64, y::Int64) in Main at In[56]:2\n",
       "[2] foo(x::Float64, y::Float64) in Main at In[56]:1\n",
       "[3] foo(x, y) in Main at In[48]:1"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# list all methods of function\n",
    "methods(foo)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(false, true)"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Parametric Methods\n",
    "isSameType(x::T, y::T) where {T} = true\n",
    "isSameType(x, y) = false\n",
    "isSameType(2, 3.4), isSameType(2, 6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "15\n"
     ]
    }
   ],
   "source": [
    "summ = 0\n",
    "# Range\n",
    "for i = 1:5\n",
    "    summ += i\n",
    "end\n",
    "println(summ)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "31\n"
     ]
    }
   ],
   "source": [
    "for i in [8,5,3]\n",
    "    summ += i\n",
    "end\n",
    "println(summ)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(4, 9, 2)"
      ]
     },
     "execution_count": 61,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "function varargs(args...)\n",
    "    return args\n",
    "end\n",
    "varargs(4, 9, 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(4, 9, 2)"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "varargs([4, 9, 2]...)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# lambda, anonymous functions\n",
    "(x -> x > 2)(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1, 2, 3)"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Closure\n",
    "# keyword return is optional\n",
    "function adder()\n",
    "    x = 0\n",
    "    function ()\n",
    "        x += 1\n",
    "        x\n",
    "    end\n",
    "end\n",
    "add = adder()\n",
    "add(), add(), add()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2-element Array{Int64,1}:\n",
       " 2\n",
       " 6"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# list comprehensions\n",
    "[2i for i in [1, 2, 3] if i&1==1 ]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Julia Types like records or structs\n",
    "\n",
    "DataType is the type that represents types, including itself."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DataType"
      ]
     },
     "execution_count": 66,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "typeof(DataType)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [],
   "source": [
    "abstract type Super end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "struct is immutable by default, [story of struct and type](https://github.com/JuliaLang/julia/pull/20418)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Point(3.2, 4.8)"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "struct Point <: Super\n",
    "    x::Float64\n",
    "    y::Float64\n",
    "end\n",
    "p = Point(3.2, 4.8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3.2, 4.8)"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "p.x, p.y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Point(3.0, 3.0)"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# outer constructor\n",
    "Point(x) = Point(x,x)\n",
    "Point(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Type[], Super, Any[Complex, Real], Any)"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "subtypes(Point), supertype(Point), subtypes(Number), supertype(Number)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "int type hierarchy: \n",
    "\n",
    "Int => Signed => Integer => Real => Number => Any\n",
    "\n",
    "All of these type, except for Int, are abstract."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [],
   "source": [
    "# bitstype was renamed to primitive type\n",
    "primitive type short <: Signed 16 end\n",
    "let sh:short = 8 end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Cat(\"Black\"), Cat(\"Inner\"))"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "abstract type Mammal end\n",
    "mutable struct Cat <: Mammal\n",
    "    color::String\n",
    "    # inner constructor\n",
    "    Cat() = new(\"Inner\")\n",
    "    Cat(x) = new(x)\n",
    "end\n",
    "Cat(\"Black\"), Cat()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Cat(\"White\")"
      ]
     },
     "execution_count": 74,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# outer constructor\n",
    "Cat() = Cat(\"White\")\n",
    "Cat()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Union{Int64, String}"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "IntOrString = Union{Int,String}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Pointy{Int32}(3, 4)"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "struct Pointy{T <: Real}\n",
    "    x::T\n",
    "    y::T\n",
    "end\n",
    "pt = Pointy{Int32}(3,4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Pointy <: Any"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(true, false)"
      ]
     },
     "execution_count": 78,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Int32 <: Signed, Pointy{Int32} <: Pointy{Signed}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "code_native() function can get assembly code"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\t.text\n",
      "; ┌ @ In[79]:1 within `area'\n",
      "\tpush\trbp\n",
      "\tmov\trbp, rsp\n",
      "; │┌ @ operators.jl:502 within `*' @ promotion.jl:314\n",
      "; ││┌ @ promotion.jl:284 within `promote'\n",
      "; │││┌ @ promotion.jl:261 within `_promote'\n",
      "; ││││┌ @ number.jl:7 within `convert'\n",
      "; │││││┌ @ float.jl:60 within `Type'\n",
      "\tvcvtsi2sd\txmm0, xmm0, ecx\n",
      "\tmovabs\trax, 341947456\n",
      "; ││└└└└\n",
      "; ││ @ operators.jl:502 within `*' @ float.jl:399\n",
      "\tvmulsd\txmm1, xmm0, qword ptr [rax]\n",
      "\tvmulsd\txmm0, xmm1, xmm0\n",
      "; │└\n",
      "\tpop\trbp\n",
      "\tret\n",
      "\tnop\tdword ptr [rax]\n",
      "; └\n"
     ]
    }
   ],
   "source": [
    "area(r) = pi * r * r \n",
    "code_native(area, (Int32,), syntax = :intel)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Parallel Computing\n",
    "## Julia [Tasks](https://docs.julialang.org/en/v1/manual/control-flow/#man-tasks-1) (aka Coroutines)\n",
    "Channels manage communication and data synchronization\n",
    "\n",
    "Channels support take!, fetch, put!, close\n",
    "\n",
    "**NOTE**: current version of Julia multiplexes all tasks onto a single OS thread\n",
    "\n",
    "Future versions of Julia may support scheduling of tasks on multiple threads"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"start\""
      ]
     },
     "execution_count": 80,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "function producer(c::Channel)\n",
    "    put!(c, \"start\")\n",
    "    for n = 1:3\n",
    "        put!(c, 2n)\n",
    "    end\n",
    "    put!(c, \"stop\")\n",
    "end\n",
    "c = Channel(producer)\n",
    "take!(c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "start\n",
      "2\n",
      "4\n",
      "6\n",
      "stop\n"
     ]
    }
   ],
   "source": [
    "for x in Channel(producer)\n",
    "    println(x)\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3-element Array{Int64,1}:\n",
       " 1\n",
       " 2\n",
       " 3"
      ]
     },
     "execution_count": 82,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ch = Channel{Int}(10)\n",
    "foreach(i->put!(ch, i), 1:3)\n",
    "close(ch)\n",
    "[i for i in ch]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A simple example using channels for inter-task communication\n",
    "\n",
    "We start 4 tasks to process data from a single jobs channel. Jobs, identified by an id (job_id), are written to the channel. Each task in this simulation reads a job_id, waits for a random amount of time and writes back a tuple of job_id and the simulated time to the results channel. Finally all the results are printed out."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4 finished in 0.38 seconds\n",
      "2 finished in 0.49 seconds\n",
      "1 finished in 0.52 seconds\n",
      "3 finished in 0.86 seconds\n",
      "7 finished in 0.6 seconds\n",
      "6 finished in 0.8 seconds\n",
      "5 finished in 0.93 seconds\n",
      "9 finished in 0.24 seconds\n",
      "11 finished in 0.22 seconds\n",
      "10 finished in 0.38 seconds\n",
      "8 finished in 0.99 seconds\n",
      "12 finished in 0.6 seconds\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "2.046906118"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "const jobs = Channel{Int}(32)\n",
    "const results = Channel{Tuple}(32)\n",
    "function do_work()\n",
    "    for job_id in jobs\n",
    "        exec_time = rand()\n",
    "        sleep(exec_time) # simulates elapsed time doing actual work\n",
    "        put!(results, (job_id, exec_time))\n",
    "    end\n",
    "end\n",
    "function make_jobs(n)\n",
    "    for i in 1:n\n",
    "        put!(jobs, i)\n",
    "    end\n",
    "end\n",
    "n = 12\n",
    "# feed the jobs channel with \"n\" jobs\n",
    "@async make_jobs(n)\n",
    "# start 4 tasks to process requests in parallel\n",
    "for i in 1:4\n",
    "    @async do_work()\n",
    "end\n",
    "# print out results\n",
    "@elapsed while n > 0\n",
    "    job_id, exec_time = take!(results)\n",
    "    println(\"$job_id finished in $(round(exec_time; digits=2)) seconds\")\n",
    "    global n = n - 1\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Multi-Threading\n",
    "[experimental] Base.Threads module"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# controlled by env JULIA_NUM_THREADS, default is 1\n",
    "Threads.nthreads()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Threads.threadid()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {},
   "outputs": [],
   "source": [
    "ids = zeros(10)\n",
    "Threads.@threads for i = 1:10\n",
    "    ids[i] = Threads.threadid()\n",
    "end"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0, 8)"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "atm = Threads.Atomic{Int}(0)\n",
    "oldatm = Threads.atomic_add!(atm, 8)\n",
    "oldatm, atm.value"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Distributed Processing\n",
    "remote references and remote calls\n",
    "\n",
    "remote references has Future and RemoteChannel\n",
    "\n",
    "A remote call returns a Future to its result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {},
   "outputs": [],
   "source": [
    "# start with 'julia -p 2'\n",
    "# let process 2 to construct a 2-by-2 random matrix\n",
    "# rc = remotecall(rand, 2, 2, 2)\n",
    "# println(fetch(rc))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Multi-dimensional Arrays\n",
    "Column first storage in Julia, not row first in C\n",
    "\n",
    "## construct fuctions\n",
    "zeros ones trues falses rand randn range"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8-element Array{Float64,1}:\n",
       " 0.0\n",
       " 0.0\n",
       " 0.0\n",
       " 0.0\n",
       " 0.0\n",
       " 0.0\n",
       " 0.0\n",
       " 0.0"
      ]
     },
     "execution_count": 89,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "f0 = zeros(8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8-element Array{Int32,1}:\n",
       " 0\n",
       " 0\n",
       " 0\n",
       " 0\n",
       " 0\n",
       " 0\n",
       " 0\n",
       " 0"
      ]
     },
     "execution_count": 90,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "i0 = zeros(Int32, 8)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2×4 Array{Float64,2}:\n",
       " 0.0  0.0  0.0  0.0\n",
       " 0.0  0.0  0.0  0.0"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = reshape(f0, 2, 4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(8, 1, (8,), (Base.OneTo(8),))"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "length(f0), ndims(f0), size(f0), axes(f0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(8, 2, (2, 4), (Base.OneTo(2), Base.OneTo(4)))"
      ]
     },
     "execution_count": 93,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "length(A), ndims(A), size(A), axes(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3×4 Array{Float64,2}:\n",
       " 0.723378  0.575545  0.490903   0.0430735\n",
       " 0.246339  0.128205  0.0850296  0.987457 \n",
       " 0.819944  0.932371  0.48747    0.926603 "
      ]
     },
     "execution_count": 94,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "R = rand(3, 4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4×2 reshape(::UnitRange{Int64}, 4, 2) with eltype Int64:\n",
       " 1  5\n",
       " 2  6\n",
       " 3  7\n",
       " 4  8"
      ]
     },
     "execution_count": 95,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = reshape(range(1,stop=8), 4, 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## concatenate\n",
    "cat vcat hcat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4×2 Array{Int64,2}:\n",
       " 2  1\n",
       " 4  6\n",
       " 7  4\n",
       " 4  8"
      ]
     },
     "execution_count": 96,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B = [2 1; 4 6; 7 4; 4 8]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4×4 Array{Int64,2}:\n",
       " 1  5  2  1\n",
       " 2  6  4  6\n",
       " 3  7  7  4\n",
       " 4  8  4  8"
      ]
     },
     "execution_count": 97,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# hcat\n",
    "[A B]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8×2 Array{Int64,2}:\n",
       " 1  5\n",
       " 2  6\n",
       " 3  7\n",
       " 4  8\n",
       " 2  1\n",
       " 4  6\n",
       " 7  4\n",
       " 4  8"
      ]
     },
     "execution_count": 98,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# vcat\n",
    "[A; B]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Comprehensions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3×4 Array{Float64,2}:\n",
       " 4.44676  4.15109  3.98181  3.08615\n",
       " 3.49268  3.25641  3.17006  4.97491\n",
       " 4.63989  4.86474  3.97494  4.85321"
      ]
     },
     "execution_count": 99,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r1 = [ 2i+3 for i = R]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.634983900184893"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sum([1/n^2 for n=1:100])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Indexing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2×4 Array{Float64,2}:\n",
       " 3.49268  3.25641  3.17006  4.97491\n",
       " 4.63989  4.86474  3.97494  4.85321"
      ]
     },
     "execution_count": 101,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r1[2:3,:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.170059198973341"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r1[8]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3-element Array{Float64,1}:\n",
       " 3.4926775444903235\n",
       " 3.974939735009108 \n",
       " 4.151090857047181 "
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r1[[2,9,4]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6-element Array{Float64,1}:\n",
       " 4.446756301844745\n",
       " 4.639887109302052\n",
       " 4.151090857047181\n",
       " 4.864742169509411\n",
       " 4.974913453921729\n",
       " 4.853206107066482"
      ]
     },
     "execution_count": 104,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Logical indexing like filter\n",
    "# same as filter(s->s>4, r1)\n",
    "r1[map(s->s>4, r1)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "6-element Array{Float64,1}:\n",
       " 4.446756301844745\n",
       " 4.639887109302052\n",
       " 4.151090857047181\n",
       " 4.864742169509411\n",
       " 4.974913453921729\n",
       " 4.853206107066482"
      ]
     },
     "execution_count": 105,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "filter(s->s>4, r1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {},
   "outputs": [],
   "source": [
    "for i in eachindex(r1)\n",
    "    #index i and r1[i]\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## operators\n",
    "-, +, *, /, \\, ^\n",
    "==, !=, ≈ (isapprox), ≉"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4×2 Array{Int64,2}:\n",
       "  3   6\n",
       "  6  12\n",
       " 10  11\n",
       "  8  16"
      ]
     },
     "execution_count": 107,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A + B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 108,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A != B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4×2 BitArray{2}:\n",
       " false  false\n",
       " false   true\n",
       " false  false\n",
       "  true   true"
      ]
     },
     "execution_count": 109,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A .== B"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4×2 BitArray{2}:\n",
       "  true  true\n",
       "  true  true\n",
       " false  true\n",
       "  true  true"
      ]
     },
     "execution_count": 110,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A .!= 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4×2 Array{Int64,2}:\n",
       "  2   5\n",
       "  8  36\n",
       " 21  28\n",
       " 16  64"
      ]
     },
     "execution_count": 111,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A .* B"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Broadcasting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "metadata": {},
   "outputs": [],
   "source": [
    "a = rand(2,1); b = rand(2,3);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2×3 Array{Float64,2}:\n",
       " 0.771396  0.965425  1.51135\n",
       " 1.85251   1.00911   1.65105"
      ]
     },
     "execution_count": 113,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "broadcast(+, a, b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "metadata": {},
   "outputs": [
    {
     "ename": "DimensionMismatch",
     "evalue": "DimensionMismatch(\"dimensions must match\")",
     "output_type": "error",
     "traceback": [
      "DimensionMismatch(\"dimensions must match\")",
      "",
      "Stacktrace:",
      " [1] promote_shape at .\\indices.jl:154 [inlined]",
      " [2] promote_shape at .\\indices.jl:145 [inlined]",
      " [3] +(::Array{Float64,2}, ::Array{Float64,2}) at .\\arraymath.jl:45",
      " [4] top-level scope at In[114]:1"
     ]
    }
   ],
   "source": [
    "a + b "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2×3 Array{Float64,2}:\n",
       " 0.771396  0.965425  1.51135\n",
       " 1.85251   1.00911   1.65105"
      ]
     },
     "execution_count": 115,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a .+ b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Julia 1.1.0",
   "language": "julia",
   "name": "julia-1.1"
  },
  "language_info": {
   "file_extension": ".jl",
   "mimetype": "application/julia",
   "name": "julia",
   "version": "1.1.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
